use std::error::Error;
use std::{fs, env};

//配置体
pub struct Config {
    pub query: String,
    pub file_path: String,
    pub ignore_case: String
}

#[allow(dead_code)]
impl Config {
    pub fn build(args: &[String]) -> Result<Config, &'static str> {
        //保证关键词和文件路径必须有
        if args.len() < 3 {
            return Err("请输入至少2个参数");
        }
        let query = args[1].clone();
        let file_path = args[2].clone();
        let mut ignore_case: String = String::new();

        //先加载环境变量，判断有没有环境变量，没有的话就赋空字符串
        #[allow(unused)]
        let env_ignore_case = env::var("IGNORE_CASE").unwrap_or_else(|_|"".to_string());
        //没有环境变量的话就跳过
        if env_ignore_case != "" {
            //Debug打印环境变量
            dbg!(&env_ignore_case);
            ignore_case = env_ignore_case;
        }

        //如果参数3存在，覆盖当前ignore_case
        if args.len() == 4 {
            ignore_case = args[3].clone();
        }

        Ok( Config{ query, file_path, ignore_case } ) 
    }
}

#[allow(dead_code)]
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
    let contents = fs::read_to_string(config.file_path)?;

    //分支判断是否敏感
    let results = if &config.ignore_case == "-i" {
        search_case_insensitive(&config.query, &contents)
    } else {
        search(&config.query, &contents)
    };

    //打印结果
    for line in results {
        println!("{line}");
    }

    Ok(())
}

//单元测试
#[cfg(test)]
#[allow(dead_code)]
mod tests {
    #[allow(dead_code,unused)]
    use super::*;

    #[test]
    fn one_result() {
        let query = "Rust";
        let contents = 
"\
Rust is here:
safe, fast, productive.
Pick three.";

        assert_eq!(vec!["Rust is here:"], search(query, contents));
    }
}

//普通检索
#[allow(dead_code,unused)]
pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
    let mut results = Vec::new();

    //.lines方法可以将字符串按行迭代
    for line in contents.lines() {
        if line.contains(query) {
            results.push(line);
        }
    }

    results
}


//大小写不敏感检索
pub fn search_case_insensitive<'a>(
    query: &str,
    contents: &'a str,
) -> Vec<&'a str> {
    let query = query.to_lowercase();
    let mut results = Vec::new();

    for line in contents.lines() {
        if line.to_lowercase().contains(&query) {
            results.push(line);
        }
    }

    results
}
